package com.aric.springbootmusic.controller;

import com.aric.springbootmusic.config.FileUploadInfo;
import com.aric.springbootmusic.entity.dto.AddMusicDTO;
import com.aric.springbootmusic.entity.dto.EditMusicDTO;
import com.aric.springbootmusic.entity.param.AddMusicParam;
import com.aric.springbootmusic.entity.param.EditMusicParam;
import com.aric.springbootmusic.entity.param.FindMusicParam;
import com.aric.springbootmusic.entity.param.QueryAllMusicParam;
import com.aric.springbootmusic.enums.SongType;
import com.aric.springbootmusic.exceptions.FileContentTypeMismatchException;
import com.aric.springbootmusic.exceptions.NameDuplicationException;
import com.aric.springbootmusic.exceptions.TimeException;
import com.aric.springbootmusic.service.MusicService;
import com.aric.springbootmusic.utils.*;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.tomcat.util.codec.binary.Base64;
import org.apache.tomcat.util.http.fileupload.FileUploadException;
import org.jaudiotagger.audio.exceptions.CannotReadException;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
import org.jaudiotagger.tag.TagException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.*;

@RestController
@RequestMapping("/music")
public class MusicController {
    @Autowired
    private MusicService musicService;
    @Autowired
    private FileUploadInfo fileUploadInfo;
    /**
     * 添加音乐信息
     * @param addMusicParam
     * @return
     * @throws NameDuplicationException
     */
    @PreAuthorize("hasAuthority('AddMusic')")
    @PostMapping("/addMusic")
    public Result addMusic(@Validated @RequestBody AddMusicParam addMusicParam) throws NameDuplicationException {
        AddMusicDTO musicDTO=new AddMusicDTO();
        musicDTO.setSongName(addMusicParam.getSongName());
        musicDTO.setSinger(addMusicParam.getSinger());
        musicDTO.setSongAddress(addMusicParam.getSongAddress());
        musicDTO.setSongRealAddress(addMusicParam.getSongRealAddress());
        if(Objects.nonNull(addMusicParam.getLyric())){
            musicDTO.setLyric(addMusicParam.getLyric());
        }
        musicDTO.setPicAddress(addMusicParam.getPicAddress());
        musicDTO.setPicRealAddress(addMusicParam.getPicRealAddress());
        musicDTO.setTotalTime(addMusicParam.getTotalTime());

        if(Integer.parseInt(addMusicParam.getSongType())==1){
            musicDTO.setSongType(SongType.SONG_TYPE_HAS_LYRIC);
        }else {
            musicDTO.setSongType(SongType.SONG_TYPE_NO_LYRIC);
        }
        musicDTO.setContentType(addMusicParam.getContentType());
        musicDTO.setIsDelete(0);
        musicDTO.setFormat(addMusicParam.getFormat());
        musicDTO.setLyricist(addMusicParam.getLyricist());
        musicDTO.setComposer(addMusicParam.getComposer());
        musicDTO.setArranger(addMusicParam.getArranger());
        musicDTO.setTempo(addMusicParam.getTempo());
        musicDTO.setRemixer(addMusicParam.getRemixer());
        musicDTO.setAlbum(addMusicParam.getAlbum());
        musicDTO.setAlbumArtist(addMusicParam.getAlbumArtist());
        musicDTO.setCopyright(addMusicParam.getCopyright());
        musicDTO.setReleaseDate(addMusicParam.getReleaseDate());
        musicDTO.setReleaseCountry(addMusicParam.getReleaseCountry());
        return musicService.addSingleMusic(musicDTO);
    }

    /**
     * 图片文件上传
     * @param file
     * @return
     * @throws IOException
     * @throws FileContentTypeMismatchException
     * @throws NoSuchPaddingException
     * @throws IllegalBlockSizeException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws BadPaddingException
     * @throws InvalidKeyException
     */
    @PreAuthorize("hasAuthority('AddMusic')")
    @PostMapping("/musicPicFileUpload")
    public Result musicPicFileUpload(MultipartFile file) throws IOException, FileContentTypeMismatchException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, InvalidKeyException {
        //上传单个文件
        boolean empty = file.isEmpty();
        if(empty){
            throw new FileUploadException("上传的文件大小是0B，文件上传失败!");
        }
        //从配置文件中获取图片文件限制大小
        Integer size = fileUploadInfo.getPicFileLimitSize();
        FileHandleUtil.isOverLimitSize(file, size);
        String realPicContentType = file.getContentType();
        //从配置文件中获取图片限制类型数组
        String[] imgContentTypes=fileUploadInfo.getPicContentTypes();
        FileHandleUtil.isMatchLimitFileContentType(imgContentTypes,realPicContentType);
        //获取前缀
        String prefix=fileUploadInfo.getUrlPrefix();
        //获取服务器的ip
        String ip = IpUtils.getResponseRealIp();
        //获取端口号
        String port=fileUploadInfo.getPort();
        //获取后缀
        String suffix = fileUploadInfo.getPicFileHttpUrlAddressSuffix();
        String httpBaseUrl = prefix+ip+":"+port+suffix;
        String realBaseUrl=fileUploadInfo.getPicFileRealAddress();
        Map<String, String> map = FileHandleUtil.uploadFile(file,httpBaseUrl,realBaseUrl);
        return ResultUtil.getResponseResult(HttpStatus.OK.value(),"上传成功！",map);
    }

    /**
     * 音乐文件上传
     * @param file
     * @return
     * @throws IOException
     * @throws FileContentTypeMismatchException
     * @throws TimeException
     * @throws CannotReadException
     * @throws TagException
     * @throws InvalidAudioFrameException
     * @throws ReadOnlyFileException
     * @throws NoSuchPaddingException
     * @throws IllegalBlockSizeException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws BadPaddingException
     * @throws InvalidKeyException
     */
    @PreAuthorize("hasAuthority('AddMusic')")
    @PostMapping("/musicFileUpload")
    public Result musicFileUpload(MultipartFile file) throws IOException, FileContentTypeMismatchException, TimeException, CannotReadException, TagException, InvalidAudioFrameException, ReadOnlyFileException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, InvalidKeyException {
        if(file.isEmpty()){
            throw new FileUploadException("上传的文件大小是0B，文件上传失败!");
        }
        Integer size = fileUploadInfo.getAudioFileLimitSize();
        FileHandleUtil.isOverLimitSize(file, size);
        String realAudioContentType = file.getContentType();
        String[] audioContentTypes=fileUploadInfo.getAudioContentTypes();
        FileHandleUtil.isMatchLimitFileContentType(audioContentTypes,realAudioContentType);
        //获取前缀
        String prefix=fileUploadInfo.getUrlPrefix();
        //获取ip
        String ip = IpUtils.getResponseRealIp();
        //获取端口号
        String port=fileUploadInfo.getPort();
        //获取后缀
        String suffix = fileUploadInfo.getAudioFileHttpUrlAddressSuffix();
        //返回url路径，这里需要配置使用
        String httpBaseUrl =prefix+ip+":"+port+suffix;
        String realBaseUrl=fileUploadInfo.getAudioFileRealAddress();
        Map<String, String> map = FileHandleUtil.uploadFile(file,httpBaseUrl,realBaseUrl);
        Map<String, String> info = FileHandleUtil.getAudioInfo(map,realAudioContentType);
        //内容类型
        info.put("contentType",realAudioContentType);
        return  ResultUtil.getResponseResult(HttpStatus.OK.value(),"上传成功！",info);
    }

    /**
     * 软删除音乐信息
     * @param id
     * @return
     */
    @PreAuthorize("hasAuthority('DeleteMusic')")
    @DeleteMapping("/deleteMusic/{id}")
    public Result deleteMusic(@PathVariable("id") String id){
        return musicService.removeMusicById(id);
    }

    /**
     * 更新音乐信息
     * @param editMusicParam
     * @return
     */
    @PreAuthorize("hasAuthority('UpdateMusic')")
    @PutMapping("/updateMusic")
    public Result updateMusic(@Validated @RequestBody EditMusicParam editMusicParam){
        EditMusicDTO musicDTO=new EditMusicDTO();
        musicDTO.setId(editMusicParam.getId());
        musicDTO.setSongName(editMusicParam.getSongName());
        musicDTO.setSinger(editMusicParam.getSinger());
        musicDTO.setSongAddress(editMusicParam.getSongAddress());
        musicDTO.setSongRealAddress(editMusicParam.getSongRealAddress());
        if(Objects.nonNull(editMusicParam.getLyric())){
            musicDTO.setLyric(editMusicParam.getLyric());
        }
        musicDTO.setPicAddress(editMusicParam.getPicAddress());
        musicDTO.setPicRealAddress(editMusicParam.getPicRealAddress());
        musicDTO.setTotalTime(editMusicParam.getTotalTime());

        if(Integer.parseInt(editMusicParam.getSongType())==1){
            musicDTO.setSongType(SongType.SONG_TYPE_HAS_LYRIC);
        }else {
            musicDTO.setSongType(SongType.SONG_TYPE_NO_LYRIC);
        }
        musicDTO.setContentType(editMusicParam.getContentType());

        musicDTO.setFormat(editMusicParam.getFormat());
        musicDTO.setLyricist(editMusicParam.getLyricist());
        musicDTO.setComposer(editMusicParam.getComposer());
        musicDTO.setArranger(editMusicParam.getArranger());
        musicDTO.setTempo(editMusicParam.getTempo());
        musicDTO.setRemixer(editMusicParam.getRemixer());
        musicDTO.setAlbum(editMusicParam.getAlbum());
        musicDTO.setAlbumArtist(editMusicParam.getAlbumArtist());
        musicDTO.setCopyright(editMusicParam.getCopyright());
        musicDTO.setReleaseDate(editMusicParam.getReleaseDate());
        musicDTO.setReleaseCountry(editMusicParam.getReleaseCountry());
        return musicService.modifyMusic(musicDTO);
    }

    /**
     * 查询单个音乐文件信息
     * @param id
     * @return
     */
    @PreAuthorize("hasAuthority('SelectMusic')")
    @GetMapping("/selectMusic/{id}")
    public Result selectSingleMusic(@PathVariable("id") String id){
        return musicService.findSingleMusic(id);
    }

    /**
     * 查询所有的音乐文件信息
     * @param findMusicParam
     * @return
     */
    @PreAuthorize("hasAuthority('MusicList')")
    @GetMapping("/selectAllMusic")
    public Result selectAllMusic(@Validated FindMusicParam findMusicParam){
        return musicService.findAllMusicByQueryCondition(findMusicParam);
    }

    /**
     * 文件下载
     * @param url
     * @param response
     * @throws IOException
     */
    /*
    @PostMapping("/download")
    public void downloadFile(@RequestParam String url,HttpServletResponse response){
        try {
            InputStream in=new FileInputStream(url);
            response.setContentType("application/octet-stream");
            //response.setHeader("Content-Disposition","attachment;fileName="+name);
            response.setHeader("Content-Length",String.valueOf(new File(url).length()));
            OutputStream os = response.getOutputStream();
            byte[] b=new byte[1024];
            int length;
            while((length=in.read(b))>0){
                os.write(b,0,length);
            }
            os.close();
            in.close();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    */
    @PostMapping("/download")
    public void downloadFile(@RequestParam String url,HttpServletResponse response) throws IOException {
        FileHandleUtil.downloadAudioFile(url,response);
    }

    /**
     * 删除上传的文件
     * @param realAddress
     * @return
     * @throws NoSuchPaddingException
     * @throws IllegalBlockSizeException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws BadPaddingException
     * @throws InvalidKeyException
     */
    @PostMapping("/removeMusic")
    public Result removeMusic(@RequestParam String realAddress) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, InvalidKeyException {
        //获取密钥
        String privateKey = SecretKey.getPrivateKey();
        //使用RSA解密
        realAddress= RSAEncryptUtil.decrypt(realAddress, Base64.decodeBase64(privateKey));

        File file=new File(realAddress);
        if(file.exists()){
            boolean b = file.delete();
            return b ? ResultUtil.getResponseResult(HttpStatus.OK.value(),"删除文件成功！",null) : ResultUtil.getResponseResult(HttpStatus.FORBIDDEN.value(), "删除失败",null);
        }
        return ResultUtil.getResponseResult(HttpStatus.FORBIDDEN.value(),"文件不存在",null);
    }

    @GetMapping("/selectShowMusic")
    public Result selectShowMusic(@Validated QueryAllMusicParam queryAllMusicParam){
        return musicService.findShowMusic(queryAllMusicParam);
    }
}
